package com.healthcarex.hip.saas.web.aspect;


import com.healthcarex.hip.saas.security.vo.SimpleUser;
import com.healthcarex.hip.saas.web.annotation.WebLog;
import com.healthcarex.hip.saas.security.model.SysUser;
import com.healthcarex.hip.saas.security.util.SecurityUtils;
import com.healthcarex.hip.saas.common.model.SysWebLog;
import com.healthcarex.hip.saas.web.service.IWebLogService;
import com.healthcarex.hip.saas.security.util.IPUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author chenpan
 * @ClassName: WebLogAspect
 * description:
 * @date 2018-04-02 15:21
 */
@Aspect
@Component
public class WebLogAspect {

    ThreadLocal<Long> startTime = new ThreadLocal<Long>();

    @Autowired
    private IWebLogService logService;

    @Pointcut("@annotation(com.healthcarex.hip.saas.web.annotation.WebLog)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
        startTime.set(System.currentTimeMillis());
        result = point.proceed();
        long time = System.currentTimeMillis() - startTime.get();
        saveLog(point, time);
        return result;
    }

    private void saveLog(ProceedingJoinPoint joinPoint, long time) {
        SimpleUser user = (SimpleUser) SecurityUtils.getCurrentUser();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysWebLog log = new SysWebLog();
        WebLog logAnnotation = method.getAnnotation(WebLog.class);
        if (logAnnotation != null) {
            log.setOperation(logAnnotation.value());
        }
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.setMethod(className + "." + methodName + "()");
        Object[] args = joinPoint.getArgs();

        if (logAnnotation.encryptParams()) {
            log.setParams("**");
        } else {
            LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
            String[] paramNames = u.getParameterNames(method);
            if (args != null && paramNames != null) {
                String params = "";
                for (int i = 0; i < args.length; i++) {
                    params += "  " + paramNames[i] + ": " + args[i];
                }
                log.setParams(params);
            }
        }


        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();
        log.setIp(IPUtils.getIpAddr(request));
        log.setUsername(user.getUsername());
        log.setTime(time);
        log.setOperationTime(new Date());
        log.setCreateTime(new Date());
        log.setLocation(null);
        log.setId(logService.getSequence("SEQ_GLOBAL"));
        this.logService.save(log);
    }
}
